﻿using System.Collections.Generic;
using System.Threading.Tasks;
using Newtonsoft.Json.Linq;
using SocialApi.Core.Request;
using SocialApi.Instagram.AppSettings;
using SocialApi.Instagram.Entities.Methods.Users;

namespace SocialApi.Instagram.Entities.Methods.Relationships
{
    internal class RelationshipMethods : IRelationshipMethods
    {
        #region Члены IRelationshipMethods

        #region Follows

        /// <summary>
        /// Возвращает список подписчиков
        /// </summary>
        /// <param name="userId">Id пользователя, список подписчиков, которого нужно вернуть</param>
        public IEnumerable<IUserMethods> Follows(long userId)
        {
            var url = InstagramService.GetMethodUrl(ApiUrls.ApiBaseUrl, ApiUrls.UserApi, string.Format(ApiUrls.UserFollows, userId));
            var jObject = JObject.Parse(Navigator.Instance.Get(url));
            InstagramService.CheckResult(jObject);
#if NET_4_5 || NET_4_0
            return jObject["data"].ToObject<IEnumerable<UserMethods>>();
#else
            return jObject["data"].ToObject<List<UserMethods>>() as IEnumerable<IUserMethods>;
#endif
        }

        /// <summary>
        /// Асинхронно возвращает список подписчиков
        /// </summary>
        /// <param name="userId">Id пользователя, список подписчиков, которого нужно вернуть</param>
        public async Task<IEnumerable<IUserMethods>> FollowsAsync(long userId)
        {
            var url = InstagramService.GetMethodUrl(ApiUrls.ApiBaseUrl, ApiUrls.UserApi, string.Format(ApiUrls.UserFollows, userId));
            var result = await Navigator.Instance.GetAsync(url);
            var jObject = JObject.Parse(result);
            InstagramService.CheckResult(jObject);
#if NET_4_5 || NET_4_0
            return jObject["data"].ToObject<IEnumerable<UserMethods>>();
#else
            return jObject["data"].ToObject<List<UserMethods>>() as IEnumerable<IUserMethods>;
#endif
        }

        #endregion

        #region Followed

        /// <summary>
        /// Получение списка пользователей на кого подписан пользователь
        /// </summary>
        /// <param name="userId">Id пользователя, список которого хотим узнать</param>
        public IEnumerable<IUserMethods> FollowedBy(long userId)
        {
            var url = InstagramService.GetMethodUrl(ApiUrls.ApiBaseUrl, ApiUrls.UserApi, string.Format(ApiUrls.UserFollowed, userId));
            var jObject = JObject.Parse(Navigator.Instance.Get(url));
            InstagramService.CheckResult(jObject);
#if NET_4_5 || NET_4_0
            return jObject["data"].ToObject<IEnumerable<UserMethods>>();
#else
            return jObject["data"].ToObject<List<UserMethods>>() as IEnumerable<IUserMethods>;
#endif
        }

        /// <summary>
        /// Асинхроное получение списка пользователей на кого подписан пользователь
        /// </summary>
        /// <param name="userId">Id пользователя, список которого хотим узнать</param>
        public async Task<IEnumerable<IUserMethods>> FollowedByAsync(long userId)
        {
            var url = InstagramService.GetMethodUrl(ApiUrls.ApiBaseUrl, ApiUrls.UserApi, string.Format(ApiUrls.UserFollowed, userId));
            var result = await Navigator.Instance.GetAsync(url);
            var jObject = JObject.Parse(result);
            InstagramService.CheckResult(jObject);
#if NET_4_5 || NET_4_0
            return jObject["data"].ToObject<IEnumerable<UserMethods>>();
#else
            return jObject["data"].ToObject<List<UserMethods>>() as IEnumerable<IUserMethods>;
#endif
        }

        #endregion

        #region RelationshipApi

        /// <summary>
        /// Получение детальной инфомации о подписчике
        /// </summary>
        /// <param name="userId">Id текущего пользователя</param>
        public IRelationshipStatus Relationship(long userId)
        {
            return Relationship(Actions.Follow, HttpMethod.Get, userId);
        }

        /// <summary>
        /// Получение детальной инфомации о подписчике
        /// </summary>
        /// <param name="actions">Действие с подписчиком</param>
        /// <param name="userId">Id текущего пользователя</param>
        public IRelationshipStatus Relationship(Actions actions, long userId)
        {
            return Relationship(actions, HttpMethod.Get, userId);
        }

        /// <summary>
        /// Получение детальной инфомации о подписчике
        /// </summary>
        /// <param name="method">Метод отправки запроса</param>
        /// <param name="userId">Id текущего пользователя</param>
        public IRelationshipStatus Relationship(HttpMethod method, long userId)
        {
            return Relationship(Actions.Follow, method, userId);
        }

        /// <summary>
        /// Получение детальной инфомации о подписчике
        /// </summary>
        /// <param name="actions">Действие с подписчиком</param>
        /// <param name="method">Метод отправки запроса</param>
        /// <param name="userId">Id текущего пользователя</param>
        public IRelationshipStatus Relationship(Actions actions, HttpMethod method, long userId)
        {
            var url = InstagramService.GetMethodUrl(ApiUrls.ApiBaseUrl, ApiUrls.UserApi, string.Format(ApiUrls.UserRelationship, userId));
            var jObject = new JObject();
            switch (method)
            {
                case HttpMethod.Get:
                    jObject = JObject.Parse(Navigator.Instance.Get(url));
                    break;
                case HttpMethod.Post:
                    jObject = JObject.Parse(Navigator.Instance.Post(url, new { action = actions.ToString().ToLowerInvariant() }));
                    break;
            }
            InstagramService.CheckResult(jObject);
            return jObject["data"].ToObject<RelationshipStatus>();

        }

        /// <summary>
        /// Асинхронное получение детальной инфомации о подписчике
        /// </summary>
        /// <param name="userId">Id текущего пользователя</param>
        public async Task<IRelationshipStatus> RelationshipAsync(long userId)
        {
            var result = await RelationshipAsync(Actions.Follow, HttpMethod.Get, userId);
            return result;
        }

        /// <summary>
        /// Асинхронное получение детальной инфомации о подписчике
        /// </summary>
        /// <param name="actions">Действие с подписчиком</param>
        /// <param name="userId">Id текущего пользователя</param>
        public async Task<IRelationshipStatus> RelationshipAsync(Actions actions, long userId)
        {
            var result = await RelationshipAsync(actions, HttpMethod.Get, userId);
            return result;
        }

        /// <summary>
        /// Асинхронное получение детальной инфомации о подписчике
        /// </summary>
        /// <param name="method">Метод отправки запроса</param>
        /// <param name="userId">Id текущего пользователя</param>
        public async Task<IRelationshipStatus> RelationshipAsync(HttpMethod method, long userId)
        {
            var result = await RelationshipAsync(Actions.Follow, method, userId);
            return result;
        }

        /// <summary>
        /// Асинхронное получение детальной инфомации о подписчике
        /// </summary>
        /// <param name="actions">Действие с подписчиком</param>
        /// <param name="method">Метод отправки запроса</param>
        /// <param name="userId">Id текущего пользователя</param>
        public async Task<IRelationshipStatus> RelationshipAsync(Actions actions, HttpMethod method, long userId)
        {
            var url = InstagramService.GetMethodUrl(ApiUrls.ApiBaseUrl, ApiUrls.UserApi, string.Format(ApiUrls.UserRelationship, userId));
            var jObject = new JObject();
            switch (method)
            {
                case HttpMethod.Get:
                    var getResult = await Navigator.Instance.GetAsync(url);
                    jObject = JObject.Parse(getResult);
                    break;
                case HttpMethod.Post:
                    var postResult = await Navigator.Instance.PostAsync(url, new { action = actions.ToString().ToLowerInvariant() });
                    jObject = JObject.Parse(postResult);
                    break;
            }
            InstagramService.CheckResult(jObject);
            return jObject["data"].ToObject<RelationshipStatus>();
        }

        #endregion

        #region RequestedBy

        /// <summary>
        /// Получения списка пользователей, которые отправили заявку на подписку
        /// </summary>
        public IEnumerable<IUserMethods> RequestedBy()
        {
            var url = InstagramService.GetMethodUrl(ApiUrls.ApiBaseUrl, ApiUrls.UserApi, ApiUrls.UserRequested);
            var jObject = JObject.Parse(Navigator.Instance.Get(url));
            InstagramService.CheckResult(jObject);
#if NET_4_5 || NET_4_0
            return jObject["data"].ToObject<IEnumerable<UserMethods>>();
#else
            return jObject["data"].ToObject<List<UserMethods>>() as IEnumerable<IUserMethods>;
#endif
        }

        /// <summary>
        /// Асинхроное получения списка пользователей, которые отправили заявку на подписку
        /// </summary>
        public async Task<IEnumerable<IUserMethods>> RequestedByAsync()
        {
            var url = InstagramService.GetMethodUrl(ApiUrls.ApiBaseUrl, ApiUrls.UserApi, ApiUrls.UserRequested);
            var result = await Navigator.Instance.GetAsync(url);
            var jObject = JObject.Parse(result);
            InstagramService.CheckResult(jObject);
#if NET_4_5 || NET_4_0
            return jObject["data"].ToObject<IEnumerable<UserMethods>>();
#else
            return jObject["data"].ToObject<List<UserMethods>>() as IEnumerable<IUserMethods>;
#endif
        }

        #endregion

        #endregion
    }
}